home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
hypercrd
/
hc2_x
/
tcprogud.sit
/
picture ƒ
/
screen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-16
|
21KB
|
717 lines
/*
* FILE: screen.c
* AUTHOR: R. Gonzalez
* CREATED: Aug. 5, 1990
*
* REVISED: Norman Gaskill
* REV. DATE: December 16, 1990
* CHANGES: Add PC_Screen code
*
* generic, mac-specific, and PC methods for multi-window screens. Use
* the Mac_Screen and PC_Screen code as a guide when writing a Screen
* descendant for a new platform.
*/
# include "screen.h"
# include "error.h"
# include <stdlib.h>
extern Error *gerror;
/******************************************************************
* Initialize screen. Derived classes call inherited method and
* initialize device_frame.
******************************************************************/
boolean Screen::init(void)
{
device_frame = new(Frame);
device_frame->init();
normalized_frame = new(Frame);
normalized_frame->init();
set_normalized_frame(0.,0.,2.,2.);
num_windows = 0;
return TRUE;
}
/******************************************************************
* Add new window to screen - up to derived class.
******************************************************************/
int Screen::new_window(Frame *frame)
{
return 0; /* must return something in Turbo C++? */
}
/******************************************************************
* Bring window to front. This is up to the derived class.
******************************************************************/
void Screen::make_closest(int window_num)
{
}
/******************************************************************
* Get coordinate frame of window in device coordinates.
* Up to derived class.
******************************************************************/
void Screen::get_window_device_frame(int window_num,
Frame *frame)
{
}
/******************************************************************
* Return screen aspect ratio: width/height in device coords.
******************************************************************/
double Screen::get_device_aspect_ratio(void)
{
double ratio;
ratio = device_frame->width/device_frame->height;
if (ratio > 0.)
return ratio;
else
return -ratio;
}
/******************************************************************
* Change coordinate system for windows and drawing routines.
* This is in terms of the width, height, and origin of
* the desired coordinate system for the whole screen. Use
* get_device_aspect_ratio to maintain aspect ratio.
******************************************************************/
void Screen::set_normalized_frame(double x,double y,
double width,double height)
{
normalized_frame->set(x,y,width,height);
}
/******************************************************************
* Sets the current drawing window. Up to derived class.
******************************************************************/
void Screen::set_current_window(int window_num)
{
}
/******************************************************************
* Sets the current drawing pen color. Up to derived class.
******************************************************************/
void Screen::set_pen_color(color x)
{
}
/******************************************************************
* Sets window background to current color. Up to derived class.
******************************************************************/
void Screen::fill_window(void)
{
}
/******************************************************************
* draw_line() is used to draw lines using device coordinates.
******************************************************************/
void Screen::draw_line(Coord2* c1,Coord2* c2)
{
move_to(c1);
draw_to(c2);
}
/******************************************************************
* Move present pen position to new position using device
* coordinates. Nothing is drawn. Up to derived class.
******************************************************************/
void Screen::move_to(Coord2* c)
{
}
/******************************************************************
* Draw from present pen position to new position using device
* coordinates. Up to derived class.
******************************************************************/
void Screen::draw_to(Coord2* c)
{
}
/******************************************************************
* mouse_button_is_down() checks whether the mouse button is down,
* returns TRUE if so, FALSE if not. Up to derived class. Make
* sure to override this if you use Screen::wait(), or override
* Screen::wait(). (Else you'll get an infinite "wait"!)
******************************************************************/
boolean Screen::mouse_button_is_down(void)
{
return FALSE;
}
/******************************************************************
* Wait until button is pressed.
******************************************************************/
void Screen::wait(void)
{
while (!mouse_button_is_down())
;
while (mouse_button_is_down())
;
}
/******************************************************************
* Destroy screen. Derived classes call inherited method.
******************************************************************/
boolean Screen::destroy(void)
{
device_frame->destroy();
delete(device_frame);
normalized_frame->destroy();
delete(normalized_frame);
return TRUE;
}
# ifdef THINK_C
#include "DialogMgr.h"
#include "EventMgr.h"
#include "TextEdit.h"
#include "MemoryMgr.h"
#include "MenuMgr.h"
#include "Quickdraw.h"
#include "WindowMgr.h"
/*------------------- Mac_Screen methods -----------------------*/
/* Functions beginning with a capital letter and variables */
/* containing capitals are declared in Mac headers, and */
/* defined in the Macintosh Toolbox. */
# define NIL_POINTER 0L
# define MOVE_TO_FRONT -1L
# define REMOVE_ALL_EVENTS 0
# define TITLE "\p"
# define VISIBLE 1
# define NO_GO_AWAY 0
# define NIL_REF_CON NIL_POINTER
/* remove following line to retain menu bar. This is recommended
to make it easier to recover from errors when debugging! */
# define NO_MBAR
/******************************************************************
* You must call init() at the beginning of main(). Likely don't
* need all these initializations; most are taken from Mark &
* Reed's "Macintosh Programming Primer", Addison-Wesley, 1989
******************************************************************/
boolean Mac_Screen::init(void)
{
double x,
y,
width,
height;
InitGraf(&thePort);
InitFonts();
FlushEvents(everyEvent,REMOVE_ALL_EVENTS);
InitWindows();
InitMenus();
TEInit();
InitDialogs(NIL_POINTER);
InitCursor();
HideCursor();
# ifdef NO_MBAR
old_mbar_height = MBarHeight;
MBarHeight = 0;
# endif
Screen::init();
width = screenBits.bounds.right - screenBits.bounds.left;
height = screenBits.bounds.top - screenBits.bounds.bottom;
x = screenBits.bounds.left + width/2.;
y = screenBits.bounds.bottom + height/2.;
device_frame->set(x,y,width,height);
normalized_frame->height = normalized_frame->width /
get_device_aspect_ratio();
current_window = NULL;
return TRUE;
}
/******************************************************************
* Add new window to screen
******************************************************************/
int Mac_Screen::new_window(Frame *frame)
{
Rect rectangle;
int left,
right,
top,
bottom;
Coord2 *old_pt,
*new_pt;
Rect mbar_rect; /* to allow window to overlap menu */
RgnHandle mbar_rgn;
WindowPtr temp_window; /* This is required due to a
bug in Think C! */
old_pt = new(Coord2);
old_pt->init();
new_pt = new(Coord2);
new_pt->init();
old_pt->set(frame->x-frame->width/2.,frame->y-frame->height/2.);
new_pt->convert(old_pt,normalized_frame,device_frame);
left = new_pt->x;
bottom = new_pt->y;
old_pt->set(frame->x+frame->width/2.,frame->y+frame->height/2.);
new_pt->convert(old_pt,normalized_frame,device_frame);
right = new_pt->x;
top = new_pt->y;
old_pt->destroy();
delete(old_pt);
new_pt->destroy();
delete(new_pt);
SetRect(&rectangle,left,top,right,bottom);
temp_window = NewWindow(NIL_POINTER,&rectangle,TITLE,
VISIBLE,plainDBox,MOVE_TO_FRONT,NO_GO_AWAY,NIL_REF_CON);
# ifdef NO_MBAR
if (top < screenBits.bounds.top+old_mbar_height)
{
if (bottom < screenBits.bounds.top+old_mbar_height)
SetRect(&mbar_rect,0,0,right-left,bottom-top);
else
SetRect(&mbar_rect,0,0,right-left,
screenBits.bounds.top+old_mbar_height-top);
mbar_rgn = NewRgn();
RectRgn(mbar_rgn,&mbar_rect);
UnionRgn(temp_window->visRgn,mbar_rgn,temp_window->visRgn);
DisposeRgn(mbar_rgn);
}
# endif
if (num_windows < MAX_WINDOWS)
{
window[num_windows++] = temp_window;
set_current_window(num_windows-1);
return num_windows-1;
}
else
{
gerror->report("Ran out of windows");
DisposeWindow(temp_window);
return num_windows-1;
}
}
/******************************************************************
* Bring window to front.
******************************************************************/
void Mac_Screen::make_closest(int window_num)
{
if (window_num > -1 && window_num < num_windows)
SelectWindow(window[window_num]);
else
gerror->report("Illegal window number");
}
/******************************************************************
* Get coordinate frame of window in device coordinates.
******************************************************************/
void Mac_Screen::get_window_device_frame(int window_num,
Frame *frame)
{
double x,
y,
width,
height;
if (window_num > -1 && window_num < num_windows)
{
width = window[window_num]->portRect.right -
window[window_num]->portRect.left;
height = window[window_num]->portRect.top -
window[window_num]->portRect.bottom;
x = window[window_num]->portRect.left + width/2.;
y = window[window_num]->portRect.bottom + height/2.;
frame->set(x,y,width,height);
}
else
gerror->report("Illegal window number");
}
/******************************************************************
* Sets the current drawing window.
******************************************************************/
void Mac_Screen::set_current_window(int window_num)
{
if (window_num > -1 && window_num < num_windows)
{
current_window = window[window_num];
SetPort(current_window);
}
else
gerror->report("Illegal window number");
}
/******************************************************************
* sets the current drawing color. The colors are defined
* in "Quickdraw.h". Call set_current_window() first!
******************************************************************/
void Mac_Screen::set_pen_color(color x)
{
if (current_window != NULL)
switch ((int) x)
{
case 0: ForeColor(blackColor);
break;
case 1: ForeColor(whiteColor);
break;
case 2: ForeColor(redColor);
break;
case 3: ForeColor(yellowColor);
break;
case 4: ForeColor(greenColor);
break;
case 5: ForeColor(blueColor);
break;
case 6: ForeColor(cyanColor);
break;
case 7: ForeColor(magentaColor);
break;
default: break;
}
else
gerror->report("Can't set color with no windows");
}
/******************************************************************
* calls the appropriate Mac Toolbox function to make the window
* the current color. Call set_current_window() first!
******************************************************************/
void Mac_Screen::fill_window(void)
{
if (current_window != NULL)
FillRect(&(current_window->portRect),black);
else
gerror->report("Can't fill window with no windows");
}
/******************************************************************
* Move present pen position to new position using device
* coordinates. Call set_current_window() first!
******************************************************************/
void Mac_Screen::move_to(Coord2* c)
{
if (current_window != NULL)
MoveTo((int) c->x,(int) c->y);
else
gerror->report("Can't move_to() with no windows");
}
/******************************************************************
* Draw from present pen position to new position using device
* coordinates. Call set_current_window() first!
******************************************************************/
void Mac_Screen::draw_to(Coord2* c)
{
if (current_window != NULL)
LineTo((int) c->x,(int) c->y);
else
gerror->report("Can't draw_to() with no windows");
}
/******************************************************************
* mouse_button_is_down() checks whether the mouse button is down,
* returns TRUE if so, FALSE if not.
******************************************************************/
boolean Mac_Screen::mouse_button_is_down(void)
{
return Button();
}
/******************************************************************
* Destroy screen.
******************************************************************/
boolean Mac_Screen::destroy(void)
{
int window_num;
Screen::destroy();
for (window_num=0 ; window_num<num_windows ; window_num++)
DisposeWindow(window[window_num]);
# ifdef NO_MBAR
MBarHeight = old_mbar_height;
# endif
return TRUE;
}
# else
/*-------------------------------- PC_Screen methods ---------------------------------*/
/*-----------------NOTE: file EGAVGA.BGI must be in current directory-----------------*/
# include <stdio.h>
# define __COLORS //for THINK_C
# include <conio.h>
# include <graphics.h> //BORLAND Turbo C++ library of graphics functions
# undef __COLORS //for THINK_C
# define LIGHTGRAY 7 //for use by floodfill
int current_window = -1; //keeps track of current window number
boolean window_defined = FALSE; //valid window variable
int win_data [MAX_WINDOWS] [6]; //window data array
/******************************************************************
* You must call init() at the beginning of main().
******************************************************************/
boolean PC_Screen::init(void)
{
int x,y,width,height;
int graphdriver = DETECT, graphmode, error_code;
Screen::init();
initgraph(&graphdriver, &graphmode, "..\\bgi"); //Initialize graphics,
error_code = graphresult(); //system must be EGA or VGA
if (error_code != grOk) //If no graphics
return(FALSE); //hardware found is found
if ((graphdriver != EGA) && (graphdriver != VGA))
{
closegraph();
return FALSE;
}
width = getmaxx();
height = getmaxy();
x = width/2;
y = height/2;
device_frame->set(x,y,width,-height);
normalized_frame->height = normalized_frame->width /
get_device_aspect_ratio();
return(TRUE); //Graphics OK return "true"
}
/******************************************************************
* Add new window to screen
******************************************************************/
int PC_Screen::new_window(Frame *frame)
{
int left,
right,
top,
bottom;
Coord2 *old_pt,
*new_pt;
old_pt = new(Coord2);
old_pt->init();
new_pt = new(Coord2);
new_pt->init();
old_pt->set(frame->x-frame->width/2.,frame->y-frame->height/2.);
new_pt->convert(old_pt,normalized_frame,device_frame);
left = new_pt->x;
bottom = new_pt->y;
old_pt->set(frame->x+frame->width/2.,frame->y+frame->height/2.);
new_pt->convert(old_pt,normalized_frame,device_frame);
right = new_pt->x;
top = new_pt->y;
old_pt->destroy();
delete(old_pt);
new_pt->destroy();
delete(new_pt);
if (num_windows < MAX_WINDOWS)
{
setviewport(left,top,right,bottom,1); //1=truncate output
win_data[num_windows][0] = left;
win_data[num_windows][1] = top;
win_data[num_windows][2] = right;
win_data[num_windows][3] = bottom;
current_window = num_windows;
num_windows++;
return num_windows-1;
}
else
{
gerror->report("Ran out of windows");
return num_windows;
}
}
/******************************************************************
* Bring window to front.
******************************************************************/
void PC_Screen::make_closest(int window_num)
{
if (window_num > -1 && window_num < num_windows)
{
current_window = window_num;
setviewport(win_data[current_window][0], //resets viewport
win_data[current_window][1],
win_data[current_window][2],
win_data[current_window][3],1); //1=truncate output
setfillstyle(SOLID_FILL, win_data[current_window][4]); //set and
floodfill(2,2,LIGHTGRAY); //flood fill current window
setcolor(win_data[current_window][5]); //reset draw color
}
else
gerror->report("Illegal window number");
}
/******************************************************************
* Get coordinate frame of window in device coordinates.
******************************************************************/
void PC_Screen::get_window_device_frame(int window_num,Frame *frame)
{
int x,
y,
width,
height;
struct viewporttype viewinfo;
if (window_num > -1 && window_num < num_windows)
{
getviewsettings(&viewinfo);
width = viewinfo.right - viewinfo.left;
height = viewinfo.bottom - viewinfo.top;
x = width/2;
y = height/2;
frame->set(x,y,width,-height);
}
else
gerror->report("Illegal window number");
}
/******************************************************************
* Sets the current drawing window.
******************************************************************/
void PC_Screen::set_current_window(int window_num)
{
if (window_num > -1 && window_num < num_windows)
{
window_defined = TRUE;
current_window = window_num;
setviewport(win_data[current_window][0], //resets viewport
win_data[current_window][1],
win_data[current_window][2],
win_data[current_window][3],1); //1=truncate output
}
else
gerror->report("Illegal window number");
}
/******************************************************************
* sets the current drawing color. Call set_current_window() first!
*----------------------------------------------------------------
* Note from R. Gonzalez: N. Gaskill had difficulty here because
* the Turbo C++ file "graphics.h" conflicted with
* my use of the identifier "color" and/or with my list of color
* constants, as defined in my "color.h". To get around this
* he had to use "# define __COLORS" and was unable to take advan-
* tage of the names given in "graphics.h". I think he could have
* gotten around this by momentarily #undef-ing my constants and
* #define-ing constants with new names for the ones given in
* graphics.h. As it is, however, he is forced to use numerical
* constants below.
******************************************************************/
void PC_Screen::set_pen_color(int color)
{
if (window_defined)
{
switch (color) //correct colors for PC
{
case 0: color = 0;
break;
case 1: color = 15;
break;
case 2: color = 4;
break;
case 3: color = 14;
break;
case 4: color = 2;
break;
case 5: color = 1;
break;
case 6: color = 3;
break;
case 7: color = 5;
break;
default: break;
}
setcolor(color); //set draw color
setfillstyle(SOLID_FILL, color); //set flood fill color
win_data[current_window][5] = color; //save draw color
}
else
gerror->report("Can't set color with no windows");
}
/******************************************************************
* Make the window the current color. Call set_current_window() first!
******************************************************************/
void PC_Screen::fill_window(void)
{
if (window_defined)
{
clearviewport(); //clear for next
floodfill(2,2,LIGHTGRAY); //fill window
win_data[current_window][4] = getcolor(); //save fill color
}
else
gerror->report("Can't fill window with no windows");
}
/******************************************************************
* Move present pen position to new position using device
* coordinates. Call set_current_window() first!
******************************************************************/
void PC_Screen::move_to(Coord2* c)
{
if (window_defined)
moveto((int) c->x,(int) c->y);
else
gerror->report("Can't move_to() with no windows");
}
/******************************************************************
* Draw from present pen position to new position using device
* coordinates. Call set_current_window() first!
******************************************************************/
void PC_Screen::draw_to(Coord2* c)
{
if (window_defined)
lineto((int) c->x,(int) c->y);
else
gerror->report("Can't draw_to() with no windows");
}
/******************************************************************
* look for keyhit.
******************************************************************/
void PC_Screen::wait(void)
{
printf("Press any key to exit");
getch();
}
/******************************************************************
* Destroy screen.
******************************************************************/
boolean PC_Screen::destroy(void)
{
int window_num;
Screen::destroy();
closegraph();
return TRUE;
}
# endif